/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.daimajia.ohosanimations.library;

import java.util.ArrayList;

/**
 * 估值器
 */
public abstract class BaseEasingMethod implements TypeEvaluator<Float> {
    /**
     * 时间
     */
    protected float mDuration;

    private ArrayList<EasingListener> mListeners = new ArrayList<>();

    /**
     * 估值监听
     */
    public interface EasingListener {
        void on(float time, float value, float start, float end, float duration);
    }

    /**
     * 添加估值监听器
     * @param listener 监听器
     */
    public void addEasingListener(EasingListener listener) {
        mListeners.add(listener);
    }

    /**
     * 添加估值监听器
     * @param ls 监听器
     */
    public void addEasingListeners(EasingListener... ls) {
        for (EasingListener listener : ls) {
            mListeners.add(listener);
        }
    }

    /**
     * 移除指定监听
     * @param listener 监听
     */
    public void removeEasingListener(EasingListener listener) {
        mListeners.remove(listener);
    }

    /**
     * 移除所有监听
     */
    public void clearEasingListeners() {
        mListeners.clear();
    }

    /**
     * 设置时间间隔
     * @param duration 时间间隔
     */
    public BaseEasingMethod(float duration) {
        mDuration = duration;
    }

    /**
     * 设置时间间隔
     * @param duration 时间间隔
     */
    public void setDuration(float duration) {
        mDuration = duration;
    }

    /**
     * 估值计算
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return 变化值
     */
    @Override
    public final Float evaluate(float fraction, Float startValue, Float endValue) {
        float time = mDuration * fraction;
        float start = startValue;
        float difference = endValue - startValue;
        float duration = mDuration;
        float result = calculate(time, start, difference, duration);
        for (EasingListener listener : mListeners) {
            listener.on(time, result, start, difference, duration);
        }
        return result;
    }

    /**
     * 估值计算
     * @param time 时间
     * @param start 开始时间
     * @param difference 时间差
     * @param duration 时间
     * @return 计算结果
     */
    public abstract Float calculate(float time, float start, float difference, float duration);
}
